package plus.easydo.easypush.dingtalk.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.taobao.api.ApiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import plus.easydo.core.exception.ExceptionFactory;
import plus.easydo.easypush.cache.ChannelInfoTokenCache;
import plus.easydo.easypush.dingtalk.DingTalkConst;
import plus.easydo.easypush.dingtalk.DingTalkWorkNoticeEnum;
import plus.easydo.easypush.dingtalk.model.DingTalkDepartment;
import plus.easydo.easypush.dingtalk.model.DingTalkSelectUsers;
import plus.easydo.easypush.dingtalk.model.DingTalkUser;
import plus.easydo.easypush.dingtalk.model.DingTalkWorkNoticeMessage;
import plus.easydo.easypush.dingtalk.service.DingTalkService;
import plus.easydo.easypush.entity.ChannelInfo;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author laoyu
 * @version 1.0
 * @date 2022/2/24
 */
@Service
public class DingTalkServiceImpl implements DingTalkService {

    private static final Logger logger = LoggerFactory.getLogger(DingTalkServiceImpl.class);

    private static final String SEND_WORK_NOTICE_URL = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2";

    @Autowired
    ChannelInfoTokenCache channelInfoTokenCache;


    public String getAccToken(ChannelInfo channelInfo) throws ApiException {
        String accessToken = channelInfoTokenCache.getChannelToken(channelInfo.getChannelType(), channelInfo.getId());
        if (CharSequenceUtil.isNotBlank(accessToken)) {
            return accessToken;
        }
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(channelInfo.getData().getString(DingTalkConst.APP_KEY));
        request.setAppsecret(channelInfo.getData().getString(DingTalkConst.APP_SECRET));
        request.setHttpMethod("GET");
        OapiGettokenResponse response;
        response = client.execute(request);
        String resultBody = response.getBody();
        JSONObject bodyJson = JSON.parseObject(resultBody);
        if (response.isSuccess()) {
            accessToken = bodyJson.getString(DingTalkConst.TOKEN_KEY);
            Long expiresIn = bodyJson.getLong(DingTalkConst.EXPIRES_IN);
            channelInfoTokenCache.cacheChannelToken(channelInfo.getChannelType(), channelInfo.getId(), accessToken, expiresIn);
            return accessToken;
        }
        throw ExceptionFactory.baseException("500", "获取钉钉token失败：" + bodyJson.getString("errmsg"));
    }

    @Override
    public boolean workNotice(DingTalkSelectUsers dingTalkSelectUsers,
                              DingTalkWorkNoticeMessage message,
                              DingTalkWorkNoticeEnum dingTalkWorkNoticeEnum,
                              ChannelInfo channelInfo) throws ApiException {
        OapiMessageCorpconversationAsyncsendV2Request request = buildMessageRequest(dingTalkSelectUsers, channelInfo);
        String token = getAccToken(channelInfo);
        switch (dingTalkWorkNoticeEnum) {
            case TEXT:
                return sendText(request, message, token);
            case LINK:
                return sendLink(request, message, token);
            case OA:
                return sendOa(request, message, token);
            case CARD:
                return senCard(request, message, token);
            case FILE:
                return sendfile(request, message, token);
            case IMAGE:
                return sendImage(request, message, token);
            case MARKDOWN:
                return sendMarkdown(request, message, token);
            case VOICE:
            default:
                return false;
        }

    }

    @Override
    public Boolean pushText(ChannelInfo channel, String title, String text) throws ApiException {
        DingTalkWorkNoticeMessage message = DingTalkWorkNoticeMessage.builder().title(title).text(text).build();
        String token = getAccToken(channel);
        OapiMessageCorpconversationAsyncsendV2Request request = buildMessageRequest(channel);
        return sendText(request, message, token);
    }

    private OapiMessageCorpconversationAsyncsendV2Request buildMessageRequest(ChannelInfo channelInfo) {
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(channelInfo.getData().getLong(DingTalkConst.AGENT_ID));
        request.setDeptIdList(channelInfo.getData().getString(DingTalkConst.DEPT_ID));
        request.setUseridList(channelInfo.getData().getString(DingTalkConst.USER_ID));
        request.setToAllUser(channelInfo.getData().getBoolean(DingTalkConst.TO_ALL_USER));
        return request;
    }

    /**
     * 构建发送消息quest对象
     *
     * @param dingTalkSelectUsers dingTalkSelectUsers
     * @return quest对象
     * @author laoyu
     * @date 2022/2/25
     */
    private OapiMessageCorpconversationAsyncsendV2Request buildMessageRequest(DingTalkSelectUsers dingTalkSelectUsers, ChannelInfo channelInfo) {
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(channelInfo.getData().getLong(DingTalkConst.AGENT_ID));
        List<DingTalkDepartment> departments = dingTalkSelectUsers.getDepartments();
        List<DingTalkUser> users = dingTalkSelectUsers.getUsers();
        if (Objects.nonNull(departments) && !departments.isEmpty()) {
            request.setDeptIdList(departments.stream().map(DingTalkDepartment::getId).collect(Collectors.joining(",")));
        }
        if (Objects.nonNull(users) && !users.isEmpty()) {
            request.setUseridList(users.stream().map(DingTalkUser::getUserId).collect(Collectors.joining(",")));
        }
        request.setToAllUser(channelInfo.getData().getBoolean(DingTalkConst.TO_ALL_USER));
        return request;
    }

    /**
     * 发送OA通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendOa(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.OA.getType());
        msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
        msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
        msg.getOa().getHead().setText(message.getTitle());
        msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body());
        msg.getOa().getBody().setContent(message.getText());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送Markdown通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendMarkdown(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.MARKDOWN.getType());
        msg.setMarkdown(new OapiMessageCorpconversationAsyncsendV2Request.Markdown());
        msg.getMarkdown().setTitle(message.getTitle());
        msg.getMarkdown().setText(message.getText());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送图片通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendImage(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.IMAGE.getType());
        msg.setImage(new OapiMessageCorpconversationAsyncsendV2Request.Image());
        msg.getImage().setMediaId(message.getMediaId());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送文件通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendfile(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.FILE.getType());
        msg.setFile(new OapiMessageCorpconversationAsyncsendV2Request.File());
        msg.getFile().setMediaId(message.getMediaId());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送卡片通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean senCard(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.CARD.getType());
        msg.setActionCard(new OapiMessageCorpconversationAsyncsendV2Request.ActionCard());
        msg.getActionCard().setTitle(message.getTitle());
        msg.getActionCard().setMarkdown(message.getText());
        msg.getActionCard().setSingleTitle(message.getSingleTitle());
        msg.getActionCard().setSingleUrl(message.getSingleUrl());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送link通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendLink(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.LINK.getType());
        msg.setLink(new OapiMessageCorpconversationAsyncsendV2Request.Link());
        msg.getLink().setTitle(message.getTitle());
        msg.getLink().setText(message.getText());
        msg.getLink().setMessageUrl(message.getMessageUrl());
        msg.getLink().setPicUrl(message.getPicUrl());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }

    /**
     * 发送文字通知
     *
     * @param request 请求
     * @param message 消息封装
     * @param token   token
     * @return boolean
     * @author laoyu
     * @date 2022/2/25
     */
    private boolean sendText(OapiMessageCorpconversationAsyncsendV2Request request, DingTalkWorkNoticeMessage message, String token) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_NOTICE_URL);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(DingTalkWorkNoticeEnum.TEXT.getType());
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(message.getText());
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, token);
        logger.info(rsp.getBody());
        return rsp.isSuccess();
    }


}
